﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ciripescu_WebRole.BL;
using Ciripescu_WebRole.Entities;
using System.Text.RegularExpressions;

namespace Ciripescu_WebRole
{
    public partial class DisplayCirips : System.Web.UI.UserControl
    {
        public delegate void ReplyEventHandler(object sender, EventArgs e);

        public event ReplyEventHandler Raspunde;

        public int NbOfItemsPerPage = Properties.Settings.Default.NbOfCiripsPerPage;
        /// <summary>
        /// sursa de unde se iau cirip-urile
        /// </summary>
        public DisplayCiripsType Type { get; set; }

        /// <summary>
        /// referinta catre componenta care scrie cirip-uri (daca este cazul - null daca nu)
        /// </summary> 
        public WriteCirip writeCirip = null;
        
        /// <summary>
        /// RowKey-ul de unde incep ciripurile pentru pagina urmatoare
        /// </summary>
        private string lastRowKey = "";

        private string oldLastRowKey = "";

        /// <summary>
        /// Pagina care se afiseaza - valabil doar pt listarea cirip-urilor unui singur user (pagina de profil) unde ne permitem sa scoatem tot din DB
        /// </summary>
        private int currentPage = 1;

        public static string FormatCiripTime(object time)
        {
            
            DateTime t = (DateTime)time;
            TimeSpan ts = DateTime.Now.Subtract(t);
            int secunde = (int)ts.TotalSeconds;
            int minute = (int)ts.TotalMinutes;
            int ore = (int)ts.TotalHours;
            int zile = (int)ts.TotalDays;
            if (secunde < 60)
            {
                return "acum sub un minut";
            }
            if (minute < 60)
            {
                if (minute == 1)
                    return "acum 1 minut";
                else
                    return "acum " + minute + " minute";
            }
            if (ore < 24)
            {
                if (ore == 1)
                    return "acum o ora";
                else 
                    return "acum " + ore + " ore";
            }
            if (zile == 1)
                return "ieri";
            else
                return "acum " + (int)ts.TotalDays + " zile";
        }

        public string NextPageLink()
        {            
            //string url = Request.CurrentExecutionFilePath;
            string url = Request.RawUrl;// va fi ceva gen /home/876653786/tip/
            string ret = "";
            //bool use_rewrite = url.IndexOf("/", 1) != -1;
            bool use_rewrite = true;
            if (use_rewrite) // se foloseste rewrite
                ret = url.Substring(0,url.IndexOf("/", 1)+1) + lastRowKey + "/"; //,1 represents next
            else
                ret = url + "?start=" + lastRowKey;

            // anumite pagini cu este cea de directmessages pot avea mai mult controale (in taburi de exemplu)
            // si trebuie sa stie pentru care din ele s-a apasat pe NextLink (de exemplu ca sa incerce tabul corect)
            // pe paginile care nu verifica querystring-ul nu le incurca cu nimic.            
            
            if (use_rewrite)
                ret += Type.ToString() + "/";
            else
                ret += "&msgtype=" + Type.ToString();

            return ret;
        }

        public string BackPageLink()
        {
            ////string url = Request.CurrentExecutionFilePath;
            //string url = Request.RawUrl;// va fi ceva gen /home/876653786/tip/
            //string ret = "";
            ////bool use_rewrite = url.IndexOf("/", 1) != -1;
            //bool use_rewrite = true;
            //if (use_rewrite) // se foloseste rewrite
            //    ret = url.Substring(0, url.IndexOf("/", 1) + 1) + oldLastRowKey + "/"; //,-1 represents back
            //else
            //    ret = url + "?start=" + oldLastRowKey; 

            //// anumite pagini cu este cea de directmessages pot avea mai mult controale (in taburi de exemplu)
            //// si trebuie sa stie pentru care din ele s-a apasat pe NextLink (de exemplu ca sa incerce tabul corect)
            //// pe paginile care nu verifica querystring-ul nu le incurca cu nimic.            

            //if (use_rewrite)
            //    ret += Type.ToString() + "/";
            //else
            //    ret += "&msgtype=" + Type.ToString();

            //return ret;
            return String.Empty;
        }
        
        public string NextPageLinkSEO()
        {
            if (Request.QueryString["UserName"] == null && Type == DisplayCiripsType.AllFromThisUser)
                return "";            
            //return url + "?userName=" + Request.QueryString["UserName"] + "&page=" + (currentPage + 1).ToString();

            

            if (Type == DisplayCiripsType.AllFromThisUser)
                return "/u/" + Request.QueryString["UserName"] + "/" + (currentPage + 1).ToString()+"/";
            else // All
            {
                string ret = "";    
                string url = Request.RawUrl;// va fi ceva gen /all/2/
                if (url.Contains(".aspx")) // dupa un postback va fi ceva de genul all.aspx?page=2
                    ret = url.Substring(0, url.IndexOf(".")) + "/" + (currentPage + 1).ToString() + "/";
                else
                    ret = url.Substring(0,url.IndexOf("/", 1)+1)+(currentPage+1).ToString()+"/";
                return ret;
                
            }
            //return url + "?userName=" + Request.QueryString["UserName"] + "&page=" + (currentPage + 1).ToString();
        }

        public string BackPageLinkSEO()
        {
            if (Request.QueryString["UserName"] == null && 
                Type == DisplayCiripsType.AllFromThisUser)
                return "";
            //return url + "?userName=" + Request.QueryString["UserName"] + "&page=" + (currentPage + 1).ToString();
            

            if (Type == DisplayCiripsType.AllFromThisUser)
                return "/u/" + Request.QueryString["UserName"] + "/" + (currentPage - 1).ToString() + "/";
            else // All
            {
                string ret = "";
                string url = Request.RawUrl;// va fi ceva gen /all/2/
                if (url.Contains(".aspx")) // dupa un postback va fi ceva de genul all.aspx?page=2
                    ret = url.Substring(0, url.IndexOf(".")) + "/" + (currentPage - 1).ToString() + "/";
                else
                    ret = url.Substring(0, url.IndexOf("/", 1) + 1) + (currentPage - 1).ToString() + "/";
                return ret;

            }
            //return url + "?userName=" + Request.QueryString["UserName"] + "&page=" + (currentPage + 1).ToString();
        }
        
        public string RaspunsLa(string InReplyToUser)
        {
            if (Type == DisplayCiripsType.Inbox || Type == DisplayCiripsType.Sent)
                return string.Empty;

            if (string.IsNullOrEmpty(InReplyToUser))
                return string.Empty;

            //return "@<a href='/profile.aspx?userName=" + InReplyToUser + "' class='mylink'>" + InReplyToUser + "</a>: ";
            return "@<a href='/u/" + InReplyToUser + "/' class='mylink'>" + InReplyToUser + "</a>: ";
        }
        
        public string EsteRaspuns(string InReplyToUser, string InReplyToId)
        {
            if (string.IsNullOrEmpty(InReplyToUser) || string.IsNullOrEmpty(InReplyToId))
                return string.Empty;
            //return " <a href='/cirip.aspx?userName=" + InReplyToUser + "&id=" + InReplyToId + "' class='mylink'>ca raspuns la " + InReplyToUser + "</a>";
            return " <a href='/cirip/" + InReplyToUser + "/" + InReplyToId + "/' class='mylink'>ca raspuns la " + InReplyToUser + "</a>";
        }
        
        protected void Page_Load(object sender, EventArgs e)
        {
            // avem linkuri diferite de next page pt pagina de profil a unui user (mai frumoase care in loc
            // sa specifice timestamp-ul de start zice pur si simplu pagina)
            // pagina de profil este singura accesibila botilor fara a fi logat
            if (Type == DisplayCiripsType.AllFromThisUser || Type == DisplayCiripsType.All)
            {
                divNextPage.Visible = false;
                divBackPage.Visible = false;
            }
            else
            {
                divNextPageSEO.Visible = false;
                divBackPageSEO.Visible = false;
            }
            // daca s-a omis username-ul pagina este eronata si nu mai are rost sa afisam linkul de SEO, userul fiind necesar pt construirea lui
            if (Request.QueryString["UserName"] == null && Type==DisplayCiripsType.AllFromThisUser)
                divNextPageSEO.Visible = false;

            //corectare pt bugul de autorefresh
            refreshFix.InnerHtml = "";
        }
        
        /// <summary>
        /// Converteste un link in cod html cu linkul respectiv si rel=nofollow
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private string ConvertUrlsToLinks(string msg)
        {
            // Magic. Do not touch!
            string regex = @"((www\.|(http|https|ftp|news|file)+\:\/\/)[&#95;.a-z0-9-]+\.[a-z0-9\/&#95;:@=.+?,##%&~-]*[^.|\'|\# |!|\(|?|,| |>|<|;|\)])";
            Regex r = new Regex(regex, RegexOptions.IgnoreCase);            
            // asa se defineste o minte intortocheata:
            return r.Replace(msg, "<a href=\"$1\" class=\"mylink\" rel=\"nofollow\">$1</a>").Replace("href=\"www", "href=\"http://www");
        }

        

        protected void Page_PreRender(object sender, EventArgs e)
        {
            CiripManager cm                = new CiripManager();
            CiripMessageManager msgManager = new CiripMessageManager();
            CiripCacheManager cache        = new CiripCacheManager();

            List<Cirip> lista = null;

            // utilizatorul ar putea sa nu fie logat daca vede pagina de profil a unui utilizator
            string userName = null;
            if (Request.QueryString["UserName"] != null)
                userName = Request.QueryString["UserName"];
            else
                if (Session["UserName"] != null)
                    userName = (string)Session["UserName"];
            else
            {
                // aici nu ar trebui sa se ajunga niciodata
                //errors.InnerHtml = "Nu s-a selectat nici un profil!";
                // nu facem nimic pt ca pagina respectiva trebuie sa-si rezolve singura input-ul defectuos (profile.aspx in acest caz)
                if (Type!= DisplayCiripsType.All)
                    return;
            }

                        
            string startRowKey = string.Empty;
            string direction   = string.Empty; //1 for next, -1 for back
            if (Request.QueryString["start"] != null)
            {
                //string[] st = Request.QueryString["start"].ToString().Split(',');
                //startRowKey = st[0];
                //direction   = st[1];
                startRowKey = oldLastRowKey = Request.QueryString["start"];
                divBackPage.Visible = true;
            }
            if (Request.QueryString["page"] != null)
            {
                string strpg = Request.QueryString["page"];
                // se poate intampla din cazua la url rewrite sa se apeleze /all/2/all.aspx?page=2 care se traduce prin /all.aspx?page=2&page=2
                // si atunci in QuerryString page=2,2
                if (strpg.Contains(","))
                    strpg = strpg.Substring(0, strpg.IndexOf(','));
                currentPage = Convert.ToInt32(strpg);
                if (currentPage == 1)
                    divBackPageSEO.Visible = false;
            }
            else
                divBackPageSEO.Visible = false;

            switch (Type)
            {
                case DisplayCiripsType.ForTheCurrentUser: lista = cm.GetNewCiripsForUserName(userName,startRowKey).ToList(); break;
                case DisplayCiripsType.Replies:           lista = msgManager.CiripMessageListToCiripList(msgManager.GetForUserName(userName, 1, startRowKey),1); break;
                case DisplayCiripsType.Inbox:             lista = msgManager.CiripMessageListToCiripList(msgManager.GetForUserName(userName, 0, startRowKey),0); break;
                case DisplayCiripsType.Sent:              lista = msgManager.CiripMessageListToCiripList(msgManager.GetForUserName(userName, 2, startRowKey),2); break;
                
                case DisplayCiripsType.All:               lista = cache.GetAllItems(currentPage).ToList(); break; 
                case DisplayCiripsType.AllFromThisUser:   lista = cm.GetCiripsFromUserName(userName, currentPage); break;
                //case DisplayCiripsType.Favorites: lista = cm.GetFavoriForUserName(userName).ToList(); break;

            }

            // daca exista linkuri in ciripuri inlocuiestele cu cod html si ai grija sa fie nofollow!
            foreach (Cirip c in lista)
                c.Content = ConvertUrlsToLinks(c.Content);

            //if (direction == "1")//next
            if(lista.Count > NbOfItemsPerPage)
                Repeater1.DataSource = lista.GetRange(0, NbOfItemsPerPage);
            else
            {
                Repeater1.DataSource = lista;
            }

            //if (direction == "-1")//back
            //    if (lista.Count > 0)
            //        Repeater1.DataSource = lista.GetRange(lista.Count - NbOfItemsPerPage, NbOfItemsPerPage);
            //    else
            //    //do nothing we need no back
            //    {
            //        divBackPage.Visible = false;
            //    }
            Repeater1.DataBind();

            // atentie: GetNewCiripsForUserName va returna totdeauna numar = cu NbOfItemsPerPage chiar daca mai este continuare
            // deci e acceasi poveste ca mai jos
            if (lista.Count >= NbOfItemsPerPage)
            {
                lastRowKey  = lista[NbOfItemsPerPage - 1].RowKey;
                
            }
            else
            {
                // ascunde linkul daca nu mai exista alte pagini
                lastRowKey = "";
                divNextPage.Visible = false;
            }                

            // pt listarea din profile (a cripurilor spuse de userul curent) 
            // dat fiind ca nu am vrut sa bag aici in pagina logica de terminare din 
            // GetCiripsFromUserName nu avem de unde sti daca pagina curenta
            // este ultima pagina, ne vom multumi cu a vedea daca pagina curenta este plina
            // cazul in care pagina asta e plina si totusi e ultima poate fi ignorat de dragul simplitatii
            if (lista.Count < NbOfItemsPerPage)
                divNextPageSEO.Visible = false;
            
        }

    
        protected void DeleteCirip(object sender, ImageClickEventArgs e)
        {
            ImageButton s = (ImageButton)sender;
            string toUserName = s.CommandArgument;
            string rowKey = s.CommandName;

            CiripManager cm = new CiripManager();
            Cirip de_sters = cm.GetSingleCirip((string)Session["UserName"], rowKey);

            if (de_sters.getUser() == (string)Session["UserName"])
            {
                cm.Delete(de_sters);
                // sterge si copia din tabela CiripMessage daca este vorba de un reply
                if (!string.IsNullOrEmpty(de_sters.InReplyToUser))
                {
                    CiripMessageManager cmm = new CiripMessageManager();
                    CiripMessage msg_de_sters = cmm.GetSingleMessage(toUserName, rowKey);
                    cmm.Delete(msg_de_sters);
                }
                // sterge si din cache daca exista!
                CiripCacheManager ccm = new CiripCacheManager();
                CiripCache cache = ccm.GetSingleCiripCache(de_sters.getUser(), de_sters.RowKey);
                if (cache != null)
                    ccm.Delete(cache);
                
            }
            else
            {
                // TODO: logare ca incercare de hacking
                Utils.WriteLog(EventLogName.Error, "Incercare de hacking. DisplayCirip.ascx.cx.Metoda DeleteCirip");
            }
        }
        
        protected void DeleteDirectMessage(object sender, ImageClickEventArgs e)
        {
            //LinkButton s = (LinkButton)sender;
            ImageButton s = (ImageButton)sender;
            string partitionKey = s.CommandArgument;
            string rowKey = s.CommandName;

            CiripMessageManager cm = new CiripMessageManager();
            CiripMessage de_sters = cm.GetSingle(partitionKey, rowKey);
                         
            if (partitionKey == (string)Session["UserName"])
            {
                cm.Delete(de_sters);                
            }
            else
            {
                // TODO: logare ca incercare de hacking
            }
        }
        
        protected void AddToFavorites(object sender, EventArgs e)
        {
            LinkButton s = (LinkButton)sender;
            string userName = s.CommandArgument;
            string rowKey = s.CommandName;
            // TODO: de scris codul pt adaugare in favorite
        }

        protected void ReplyToCirip(object sender, ImageClickEventArgs e)
        {
            //LinkButton s = (LinkButton)sender;
            ImageButton  s = (ImageButton)sender;  
            string userName = s.CommandArgument;
            string rowKey   = s.CommandName;
            
            if (writeCirip != null)
            {                
                writeCirip.InReplyToUser = userName;
                writeCirip.InReplyToId = rowKey;
                writeCirip.UpdateDisplay();
            }
            else
            {
                //Response.Redirect("home.aspx?InReplyToUser=" + userName + "&InReplyToId=" + rowKey);
                Response.Redirect("/reply/" + userName + "/" + rowKey+"/");
            }

            if (Request.Url.ToString().Contains("home"))
                Raspunde(this, e);
        }
        
        protected void ReplyToDirectMessage(object sender, ImageClickEventArgs e)
        {
            //LinkButton s = (LinkButton)sender;
            ImageButton  s = (ImageButton)sender;
            string fromUserName = s.CommandArgument;
            string rowKey = s.CommandName;

            //Response.Redirect("/sendmessage.aspx?userName=" + fromUserName);
            Response.Redirect("/sendmessage/" + fromUserName+"/");

        }
        
        protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            Cirip c = (Cirip)e.Item.DataItem;           
            
            if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem)
                return;

            // cred ca eram beat cand am pus atatea IF-uri alandala
            // nefericitul ca va debagui de ce apar si dispar aiurea butoanele va avea placerea sa puna un CASE in loc - deocamdata merg

            Label linkUserName = (Label)e.Item.FindControl("lblUserName");
            Label lblPoza = (Label)e.Item.FindControl("lblPoza");
            //LinkButton del = (LinkButton)e.Item.FindControl("btnDelete");
            //LinkButton reply = (LinkButton)e.Item.FindControl("btnReply");
            //LinkButton fav = (LinkButton)e.Item.FindControl("btnFavorites");
            //LinkButton replyDirect = (LinkButton)e.Item.FindControl("btnReplyToDirectMessage");
            ImageButton del = (ImageButton)e.Item.FindControl("btnDelete");
            ImageButton reply = (ImageButton)e.Item.FindControl("btnReply");
            //ImageButton fav = (ImageButton)e.Item.FindControl("btnFavorites");
            ImageButton replyDirect = (ImageButton)e.Item.FindControl("btnReplyToDirectMessage");    
            // pe pagina de profil se ascunde poza si numele userului (fiind evidente)
            if (Type == DisplayCiripsType.AllFromThisUser)
            {                
                linkUserName.Visible = false;                
                lblPoza.Visible = false;
            }
                               

            if (Type == DisplayCiripsType.Inbox || Type == DisplayCiripsType.Sent)
            {
                // pentru mesaje directe avem nevoie de doar de butonul de delete specializat pe direct messages si de cel de reply tot pt direct messags
                del.Visible = false;
                reply.Visible = false;
                //fav.Visible = false;
                linkUserName.Visible = false; // ascundem si userul care a zis-o pt ca nu va fi corect pt mesajele din Sent - Mesjul in sine va contine linkul corect
                if (Type == DisplayCiripsType.Sent) // nu are sens sa iti dai reply chiar tie
                    replyDirect.Visible = false;
            }
            else
            {                
                ImageButton delDirect = (ImageButton)e.Item.FindControl("btnDeleteDirectMessage");
                
                delDirect.Visible = false;
                replyDirect.Visible = false;
            }

            if (Session["UserName"] == null) // user nelogat
            {
                reply.Visible = false;
                //fav.Visible = false;
                del.Visible = false;
            }
            else
            {
                // daca e ciripul userului curent
                if (c.getUser() == (string)Session["UserName"])
                {
                    reply.Visible = false;                    
                }
                else
                // daca e ciripul altuia
                {
                    del.Visible = false;
                }
            }
        }


        protected string GetPictureUri(object userId)
        {
            if (userId==null)
                return "";

            UserManager uManag = new UserManager();
            User usr = uManag.GetItem((string)userId);
            // de ex la userul admin creat automat nu exista
            if (string.IsNullOrEmpty(usr.PictureUri))
                return "";
            else
            return usr.PictureUri.ToString();
        }

        public void AutomaticRefresh()
        {
            //if (Type == DisplayCiripsType.ForTheCurrentUser)
            {
                refreshFix.InnerHtml = "auto";
            }
        }
    }
    public enum DisplayCiripsType
    {
        /// <summary>
        /// Tot ce ar trebui sa vada acest user pe pagina de home - tot ce e destinat pt el: 
        /// de la alti useri pe care ii urmareste, reply-uri si ciripurile proprii
        /// </summary>
        ForTheCurrentUser, 
        /// <summary>
        /// doar reply-urile
        /// </summary>
        Replies,
        /// <summary>
        /// Toate ciripurile de pe site, indiferent cine le-a zis
        /// </summary>
        All, 
        /// <summary>
        /// Doar ciripurile zise de el
        /// Este pentru pagina de profil! Are un sistem separat de calculare si selectarii a paginarii mai SEO friendly
        /// dar mai ineficient
        /// </summary>
        AllFromThisUser, 
        /// <summary>
        /// Tot ce a bagat userul in favorites
        /// </summary>
        Favorites,
        Inbox,
        Sent
    }
}